package top.magicpotato.fast.quartz.config;

import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import top.magicpotato.fast.quartz.annotation.QuartzBeanPostProcessor;
import top.magicpotato.fast.quartz.listener.QuartzJobListener;

import java.util.ArrayList;
import java.util.Properties;
import java.util.Set;

/**
 * @author ycl
 * 主配置类 用来提供调度器
 */
@Configuration
@EnableConfigurationProperties(QuartzProperties.class)
public class QuartzAutoConfiguration {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private QuartzProperties quartzProperties;

    /**
     * 用来获取spring实例对象 设置到静态变量中
     *
     * @return
     */
    @Bean(name = "quartzManager")
    public QuartzManager quartzManager() {
        return new QuartzManager();
    }

    @Bean
    @DependsOn("quartzManager")
    public Scheduler scheduler() throws SchedulerException {
        StdSchedulerFactory fact = new StdSchedulerFactory(genProperties());
        Scheduler scheduler = fact.getScheduler();

        // 移除已存在的所有任务
        Set<JobKey> aNull = scheduler.getJobKeys(GroupMatcher.anyGroup());
        if (scheduler.deleteJobs(new ArrayList<>(aNull))) {
            logger.info("移除全部{}个任务", aNull.size());
        }
        // 添加job监听器
        scheduler.getListenerManager().addJobListener(new QuartzJobListener());
        scheduler.start();
        return scheduler;
    }

    @Bean
    public QuartzBeanPostProcessor quartzBeanPostProcessor(Scheduler scheduler) {
        return new QuartzBeanPostProcessor(scheduler);
    }

    private Properties genProperties() {
        Properties properties = new Properties();
        properties.put("org.quartz.scheduler.instanceName", quartzProperties.getInstanceName());
        properties.put("org.quartz.scheduler.instanceId", quartzProperties.getInstanceId());
        properties.put("org.quartz.threadPool.threadCount", quartzProperties.getThreadCount());
        properties.put("org.quartz.jobStore.isClustered", quartzProperties.getIsClustered());
        properties.put("org.quartz.jobStore.clusterCheckinInterval", quartzProperties.getClusterCheckinInterval());
        properties.put("org.quartz.jobStore.class", quartzProperties.getJobStoreClass());
        properties.put("org.quartz.jobStore.driverDelegateClass", quartzProperties.getDriverDelegateClass());
        properties.put("org.quartz.jobStore.useProperties", quartzProperties.getUseProperties());
        properties.put("org.quartz.jobStore.dataSource", quartzProperties.getDataSource());
        properties.put("org.quartz.jobStore.tablePrefix", quartzProperties.getTablePrefix());
        properties.put("org.quartz.dataSource." + quartzProperties.getDataSource() + ".connectionProvider.class", quartzProperties.getConnectionProvider());
        properties.put("org.quartz.jobStore.misfireThreshold", quartzProperties.getMisfireThreshold());
        return properties;
    }
}
